import os
from typing import TextIO

from bean.Constants import Constants
from bean.TableInfo import TableInfo

from builder.CommentBuilder import CommentBuilder
from utils.StringUtils import uppercase_first_char, lower_first_char


class ServiceImplBuilder:

    @staticmethod
    def execute_build(table_info: TableInfo) -> None:
        if not os.path.exists(Constants.get_instance().SERVICE_IMPL_PATH):
            os.makedirs(Constants.get_instance().SERVICE_IMPL_PATH)

        with open(Constants.get_instance().SERVICE_IMPL_PATH + f"{table_info.bean_name}ServiceImpl.java", "w",
                  encoding="utf-8") as f:
            f.write(f"package {Constants.get_instance().PACKAGE_SERVICE_IMPL};")
            f.write("\n\n")
            ServiceImplBuilder.build_class_and_imports(f, table_info)
            f.write("\n")
            ServiceImplBuilder.build_impls(f, table_info)
            f.write("}")

    @staticmethod
    def build_class_and_imports(file_pointer: TextIO, table_info: TableInfo) -> None:
        def build_service_comment():
            if table_info.comment != "":
                CommentBuilder.build_class_comment(file_pointer, table_info.comment + "  业务服务")
            else:
                CommentBuilder.build_class_comment(file_pointer, table_info.comment)

        file_pointer.write(f"import {Constants.get_instance().PACKAGE_ENUM}.PageSize;")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_PARAM}.SimplePage;")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_SERVICE}.{table_info.bean_name}Service;")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_PO}.{table_info.bean_name};")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_PARAM}.{table_info.bean_param_name};")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_VO}.PaginationResultVO;")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_MAPPERS}.{table_info.bean_name}{Constants.get_instance().SUFFIX_MAPPERS};")
        file_pointer.write("\n\n")
        file_pointer.write("import org.springframework.stereotype.Service;")
        file_pointer.write("\n")
        file_pointer.write("import jakarta.annotation.Resource;")
        file_pointer.write("\n\n")
        file_pointer.write(f"import java.util.Date;")
        file_pointer.write("\n")
        file_pointer.write("import java.util.List;")
        file_pointer.write("\n")
        build_service_comment()

        file_pointer.write("\n")
        file_pointer.write(f"@Service(\"{table_info.bean_name}Service\")")
        file_pointer.write("\n")
        file_pointer.write(f"public class {table_info.bean_name}ServiceImpl implements {table_info.bean_name}Service{{")

    @staticmethod
    def build_impls(file_pointer: TextIO, table_info: TableInfo) -> None:
        def build_impls_helper(comment: str, content: str, retraction: str = "", inner_code: str = "") -> None:
            file_pointer.write("\n")
            CommentBuilder.build_filed_comment(file_pointer, comment, retraction)
            file_pointer.write("\n")
            file_pointer.write(f"{retraction}@Override")
            file_pointer.write("\n")
            file_pointer.write(retraction + "public " + content)
            file_pointer.write(f"{{\n{retraction}{inner_code}\n{retraction}}}")
            file_pointer.write("\n")

        file_pointer.write("\n")
        file_pointer.write("\t@Resource")
        file_pointer.write("\n")
        file_pointer.write(
            f"\tprivate {table_info.bean_name}{Constants.get_instance().SUFFIX_MAPPERS}<{table_info.bean_name}, {table_info.bean_param_name}> {lower_first_char(table_info.bean_name)}{Constants.get_instance().SUFFIX_MAPPERS};"
        )

        mappers_name = lower_first_char(table_info.bean_name) + Constants.get_instance().SUFFIX_MAPPERS

        build_impls_helper(
            "根据条件查询列表",
            f"List<{table_info.bean_name}> findListByParam({table_info.bean_param_name} param)",
            "\t",
            f"\treturn this.{mappers_name}.selectList(param);"
        )

        build_impls_helper(
            "根据列表查询数量",
            f"Long findCountByParam({table_info.bean_param_name} param)",
            "\t",
            f"\treturn this.{mappers_name}.selectCount(param);"
        )
        paging_inner = f"\tLong count = this.findCountByParam({lower_first_char(Constants.get_instance().SUFFIX_BEAN_PARAM)});"
        paging_inner += "\n"
        paging_inner += "\t\tLong pageSize = query.getPageSize() == null ? PageSize.SIZE15.getSize() : query.getPageSize();"
        paging_inner += "\n"
        paging_inner += "\t\tSimplePage page = new SimplePage(query.getPageNo(), count, pageSize);"
        paging_inner += "\n"
        paging_inner += "\t\tquery.setSimplePage(page);"
        paging_inner += "\n"
        paging_inner += f"\t\tList<{table_info.bean_name}> list = this.findListByParam(query);"
        paging_inner += "\n"
        paging_inner += f"\t\tPaginationResultVO<{table_info.bean_name}> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);"
        paging_inner += "\n"
        paging_inner += "\t\treturn result;"

        build_impls_helper(
            "分页查询",
            f"PaginationResultVO<{table_info.bean_name}> findListByPage({table_info.bean_param_name} query)",
            "\t",
            paging_inner
        )


        build_impls_helper(
            "新增",
            f"Integer add({table_info.bean_name} bean)",
            "\t",
            f"\treturn this.{mappers_name}.insert(bean);"
        )

        add_batch_inner = "\tif(listBean == null || listBean.isEmpty()) return 0;"
        add_batch_inner += "\n"
        add_batch_inner += f"\t\treturn this.{mappers_name}.insertBatch(listBean);"
        build_impls_helper(
            "批量新增",
            f"Integer addBatch(List<{table_info.bean_name}> listBean)",
            "\t",
            add_batch_inner
        )

        add_batch_or_update_inner = "\tif(listBean == null || listBean.isEmpty()) return 0;"
        add_batch_or_update_inner += "\n"
        add_batch_or_update_inner += f"\t\treturn this.{mappers_name}.insertOrUpdateBatch(listBean);"

        build_impls_helper(
            "批量新增/修改",
            f"Integer addOrUpdateBatch(List<{table_info.bean_name}> listBean)",
            "\t",
            add_batch_or_update_inner
        )

        for i in table_info.field_map.values():
            props = uppercase_first_char(i.property_name)
            build_impls_helper(
                f"根据{i.property_name}查询",
                f"{table_info.bean_name} get{table_info.bean_name}By{props}({i.java_type} {i.property_name})",
                "\t",
                f"\treturn this.{mappers_name}.selectBy{props}({i.property_name});"
            )

            build_impls_helper(
                f"根据{i.property_name}修改",
                f"Integer update{table_info.bean_name}By{props}({table_info.bean_name} bean, {i.java_type} {i.property_name})",
                "\t",
                f"\treturn this.{mappers_name}.updateBy{props}(bean, {i.property_name});"
            )

            build_impls_helper(
                f"根据{i.property_name}删除",
                f"Integer delete{table_info.bean_name}By{props}({table_info.bean_name} bean, {i.java_type} {i.property_name})",
                "\t",
                f"\treturn this.{mappers_name}.deleteBy{props}(bean, {i.property_name});"
            )
